<?php
class Server {
    private $host = '0.0.0.0';
    private $port = 6666;
    private $listen_socket = null;
    private $client_array  = array();
    private $closure_array = array();
    public function init() {
        $listen_socket = socket_create( AF_INET, SOCK_STREAM, SOL_TCP );
        socket_set_option( $listen_socket, SOL_SOCKET, SO_REUSEADDR, 1 );
        socket_set_option( $listen_socket, SOL_SOCKET, SO_REUSEPORT, 1 );
        socket_bind( $listen_socket, $this->host, $this->port );
        socket_listen( $listen_socket );
        socket_set_nonblock( $listen_socket );
        $this->client = array( $listen_socket );
        $this->listen_socket = $listen_socket;
    }
    // 这个函数就相当于注册回调函数...
    public function on( $event_name, Closure $func ) {
        $this->closure_array[ $event_name ] = $func;
    }
    public function run() {
        while ( true ) {
            $read      = $this->client;
            $write     = array();
            $exception = array();
            $ret       = socket_select( $read, $write, $exception, NULL );
            if ( $ret <= 0 ) {
                continue;
            }
            // 就是说，如果 listen-socket 中有事件，listen-socket能有啥事件：就是用新的客户端来了
            if ( in_array( $this->listen_socket, $read ) ) {
                $connection_socket = socket_accept( $this->listen_socket );
                if ( !$connection_socket ) {
                    continue;
                }
                $this->client[] = $connection_socket;
                $key    = array_search( $this->listen_socket, $read );
                unset( $read[ $key ] );
                // connect时：触发
                $func = isset( $this->closure_array['connect'] ) ? $this->closure_array['connect'] : false ;
                if ( false !== $func ) {
                    call_user_func_array( $func, array() );
                }
            }
            // 对于其他socket
            foreach( $read as $read_key => $read_fd ) {
                socket_recv( $read_fd, $recv_content, 1024, 0 );
                if ( !$recv_content ) {
                    unset( $this->client[ $read_key ] );
                    socket_close( $read_fd );
                    continue;
                }
                // 收到消息时：触发
                $func = isset( $this->closure_array['message'] ) ? $this->closure_array['message'] : false ;
                if ( false !== $func ) {
                    call_user_func_array( $func, array( $recv_content ) );
                }
                unset( $this->client[ $read_key ] );
                socket_shutdown( $read_fd );
                socket_close( $read_fd );
            }
        }
    }
}
$server = new Server();
$server->init();
// 这里通过on函数来注册
// 这里就是利用了PHP里的Closure，其实下面function就是Closure
$server->on( 'connect', function() {
    echo "触发connect".PHP_EOL;
} );
$server->on( 'message', function( $data ) {
    echo "触发message，收到数据：".$data.PHP_EOL;
} );
$server->run();